    <h1 class="pageHeader">Spica Framework - Manual - Hand-on guide</h1>

    <h2 class="header">Làm việc với block và block group</h2>
    <p>Chúng ta đã làm quen với khái niệm block và block group qua bài
    <a href="docs/guide/page/pname/tutorial_simpletheme" class="hasIcon">Viết ứng dụng đơn giản có dùng layout và theme (căn bản)</a>
    và <a href="docs/guide/page/pname/concept_view" class="hasIcon">Các khái niệm về View: Theme, Template, Layout, Block, BlockGroup</a>
    </p>
    <h3>Tạo Block</h3>
    <p>Việc định nghĩa block luôn gắn liền với page layout và theme. Giả sử như chúng ta
    cần chia trang thành 3 phần: header, main content và footer, chúng ta có
    thể nghĩ đến việc đặt header thành một block riêng. Vậy hãy khai báo lớp
    sinh nội dung cho block này:</p>

<pre class="brush: php; highlight: [5];">
&lt;?php

class DefaultHeaderBlock extends SpicaPageBlock
{
    protected $_templateFile = 'defaultHeader';
}

?&gt;

</pre>
    <p>Block là một PHP class mở rộng lớp <code>SpicaPageBlock</code>. Lớp này được khai báo trong
    một file cùng tên. Quy tắc như sau:</p>
    <ul>
      <li>Tên lớp: <code>DefaultHeaderBlock</code></li>
      <li>Nơi đặt: <code>apps/{currentApplication}/block/DefaultHeaderBlock.php</code></li>
    </ul>
    <p>Khai báo <code>protected $_templateFile = 'defaultHeader';</code> cho thấy lớp này khi tạo đối
    tượng sẽ nạp một file template có tên là <code>defaultHeader</code>. Quy tắc:</p>
    <ul>
      <li>Khai báo: <code class="g">protected $_templateFile = 'defaultHeader';</code></li>
      <li>Tên template: <code>defaultHeader</code></li>
      <li>Nơi đặt: <code>apps/{currentApplication}/view/theme/{currentTheme}/block/defaultHeader.tpl.php</code></li>
    </ul>
    <p>Chúng ta có thể đặt template file vào một thư mục con của thư mục <code>theme/{currentTheme}/block</code>
    nói trên. Quy tắc: </p>
    <ul>
      <li><code class="g">protected $_templateFile = 'aDirectory/defaultHeader';</code></li>
      <li>Template file: <code>apps/{currentApplication}/view/theme/{currentTheme}/block/</code><code class="g">aDirectory</code><code>/defaultHeader.tpl.php</code></li>
    </ul>

    <p>Việc khởi tạo đối tượng <code>DefaultHeaderBlock</code> và thu hồi nội dung của
    nó diễn ra như sau:</p>

<pre class="brush: php; highlight: [14];">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
&lt;?php echo spica_html_base_tag(); ?&gt;
&lt;title&gt;&lt;?php echo $this-&gt;pageTitle; ?&gt;&lt;/title&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;link rel="stylesheet" href="public/spica/css/reset.css" type="text/css" media="all" /&gt;
&lt;link rel="stylesheet" href="public/spica/css/docs.css" type="text/css" media="all" /&gt;
&lt;link rel="stylesheet" href="public/spica/syntaxhighlighter/styles/shCore.css" type="text/css" media="all" /&gt;
&lt;link rel="stylesheet" href="public/spica/syntaxhighlighter/styles/shThemeSpica.css" type="text/css" media="all" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="wrapper"&gt;
  &lt;?php echo $this-&gt;fetchBlock('DefaultHeaderBlock'); ?&gt;
  &lt;div id="main"&gt;
  &lt;?php echo $this-&gt;fetchBody(); ?&gt;
  &lt;/div&gt;
  &lt;?php echo $this-&gt;fetchBlock('DefaultFooterBlock'); ?&gt;
&lt;/div&gt;
&lt;script type="text/javascript" src="public/spica/syntaxhighlighter/scripts/shBrushJScript.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
  SyntaxHighlighter.config.clipboardSwf = 'public/spica/syntaxhighlighter/scripts/clipboard.swf';
  SyntaxHighlighter.all();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

</pre>
    <p>Đoạn code trên là nội dung của layout template file của một theme.</p>
    <p>Lời gọi <code>$this-&gt;fetchBlock('DefaultHeaderBlock');</code> sẽ khởi tạo một
    đối tượng cho lớp <code>DefaultHeaderBlock</code> và yêu cầu nó trả về nội dung.</p>

    <p>Block <code>DefaultHeaderBlock</code> hiện giờ chỉ làm một nhiệm vụ là đọc template file của nó và trả lại.
    Trong các tình huống thực tế, block có thể đảm nhiệm việc đọc nội dung từ database hay
    từ các nguồn dữ liệu khác, populate nó vào template file, chuyển đổi template file
    về HTML rồi trả lại.</p>

<pre class="brush: php; highlight: [10, 37];">
&lt;?php

class SpicaDocsNoteBlock extends SpicaPageBlock
{
    /**
     * Template file.
     *
     * @var string
     */
    protected $_templateFile = 'vi_VN/docsNoteBlock';

    /**
     * Page ID.
     *
     * @var int
     */
    public $pageId;

    /**
     * Page ID checking message.
     *
     * @var string
     */
    public $pageCheckMessage;

    /**
     * Page notes.
     *
     * @var SpicaRowList
     */
    public $notes;

    /**
     * (non-PHPdoc)
     * @see trunk/library/spica/core/view/SpicaPageBlock#initialize()
     */
    public function initialize()
    {
        include_once 'service/SpicaDocsNoteService.php';
        $this-&gt;_templateFile = SpicaContext::getLocaleName().'/docsNoteBlock';
        $docsNoteService     = new SpicaDocsNoteService('spicadocs');

        try
        {
            $pageId       = $docsNoteService-&gt;findPageId(SpicaRequest::getController(), SpicaRequest::get('pname'));
            $this-&gt;notes  = $docsNoteService-&gt;findNotesByPageId($pageId);
            $this-&gt;pageId = $pageId;
        }
        catch (Exception $e)
        {
            $this-&gt;pageCheckMessage = $e-&gt;getMessage();
            $this-&gt;notes  = new SpicaRowList();
            $this-&gt;notes-&gt;setReadable(true);
            $this-&gt;notes-&gt;setMessage($e-&gt;getMessage());
        }
    }
}

?&gt;

</pre>

    <p>Block mang tên <code>SpicaDocsNoteBlock</code> sử dụng template file nằm tại
    <code>apps/{currentApplication}/view/theme/{currentTheme}/block/vi_VN/docsNoteBlock.tpl.php</code>
    theo như quy ước. Khác với <code>DefaultHeaderBlock</code>, nó có một phương thức public
    đặc biệt có tên là <code>initialize()</code>. Phương thức này sẽ chạy khi một đối
    tượng của <code>SpicaDocsNoteBlock</code> được tạo ra và được yêu cầu trả về nội dung.
    Theo đoạn code trên, <code>SpicaDocsNoteBlock</code> tương tác với các lớp xử lý dữ liệu
    để lấy về các dữ liệu mà nó cần và chuyển vào các public property như <code>$notes</code>
    và <code>$pageId</code>. Giá trị của các property này sẽ được populate vào template file như sau:</p>

<pre class="brush: css; highlight: [25, 33, 36];">

    &lt;div class="docsNotes"&gt;
    &lt;h3&gt;Add your comments&lt;/h3&gt;
    &lt;div id="messages"&gt;&lt;/div&gt;
    &lt;?php if (null !== $this-&gt;pageCheckMessage): ?&gt;
    &lt;div class="warning"&gt;&lt;?php echo $this-&gt;pageCheckMessage; ?&gt;&lt;/div&gt;
    &lt;?php endif; ?&gt;
    &lt;form id="note" method="post" action="docs/note/add"&gt;
      &lt;div&gt;
        &lt;label&gt;Email or name:&lt;/label&gt;
        &lt;div class="right"&gt;&lt;input type="text" name="username" id="username" size="60" maxlength="40" value="user@example.com" /&gt;&lt;/div&gt;
        &lt;div class="warning" id="usernameFeedback" style="display:none"&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;label&gt;Your comment:&lt;/label&gt;
        &lt;div class="right"&gt;&lt;textarea name="note" id="noteContent" rows="10" cols="132"&gt;&lt;/textarea&gt;
        &lt;div class="warning" id="noteFeedback" style="display:none"&gt;&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;label&gt;&nbsp;&lt;/label&gt;
        &lt;div class="right"&gt;
          &lt;input type="button" name="action" value="Preview" /&gt;
          &lt;input type="submit" name="action" value="Add Note" /&gt;
          &lt;input type="hidden" name="reply_to" value="" /&gt;
          &lt;input type="hidden" name="page_id" value="&lt;?php echo $this-&gt;pageId; ?&gt;" /&gt;
          &lt;div class="warning" id="pageIDFeedback" style="display:none"&gt;&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/form&gt;
    &lt;/div&gt;
    &lt;script type="text/javascript" src="public/spica/js/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="public/spica/js/addnote.js"&gt;&lt;/script&gt;
    &lt;?php if ($this-&gt;notes-&gt;isReadable()): ?&gt;
    &lt;h3&gt;User comments&lt;/h3&gt;
    &lt;table class="simple" id="noteList"&gt;
    &lt;?php foreach ($this-&gt;notes as $note): ?&gt;
      &lt;tr class="header"&gt;
        &lt;th&gt;&lt;?php echo $note-&gt;get('note_username'); ?&gt;&lt;/th&gt;
        &lt;th&gt;&lt;?php echo $note-&gt;get('note_dtime'); ?&gt;&lt;/th&gt;
      &lt;/tr&gt;
      &lt;tr class="even"&gt;
        &lt;td colspan="2"&gt;&lt;?php echo SpicaStringUtils::normalizeHtml($note-&gt;get('note_content')); ?&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;?php endforeach; ?&gt;
    &lt;/table&gt;
    &lt;?php else: ?&gt;
    &lt;div class="warning"&gt;&lt;?php echo $this-&gt;notes-&gt;getMessage(); ?&gt;&lt;/div&gt;
    &lt;?php endif; ?&gt;

</pre>


    <?php echo $this->fetchBlock('welcome/SpicaDocsNoteBlock'); ?>